﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Mal.Balades.Admin.Services;

namespace Mal.Balades.Admin.ViewModels.FeedViewModels
{
    public class FeedsViewModel : PageViewModelBase
    {
        #region Fields
        IAdminService service;

        private bool isLoading;
        private bool isUpdating;
        private bool isEnabled = true;
        private bool isUpdateFeedItemsEnabled = false;
        private ObservableCollection<FeedViewModel> feeds;
        private ReadOnlyCollection<IFeed> sourceFeeds;
        private bool isAllSelected;

        private RelayCommand updateFeedItemsCommand;
        #endregion

        #region Construction / Destruction
        public FeedsViewModel()
        {
            if (this.IsInDesignMode)
            {

            }
            else
            {
                this.service = AdminServiceFactory.GetInstance();
                this.service.GetFeedsCompleted += new ServiceResponse<ReadOnlyCollection<IFeed>>(this.OnGetFeedsCompleted);
                this.service.UpdateFeedItemsCompleted += new ServiceResponse<bool>(this.OnUpdateFeedItemsCompleted);
                this.LoadFeeds();
            }
        }
        #endregion

        #region enum, struct, class

        #endregion

        #region Properties
        public bool IsAllSelected
        {
            get
            {
                return this.isAllSelected;
            }

            set
            {
                if (this.isAllSelected != value)
                {
                    this.isAllSelected = value;
                    RaisePropertyChanged("IsAllSelected");

                    this.SelectAllFeeds(this.isAllSelected);
                }
            }
        }

        public bool IsLoading
        {
            get
            {
                return this.isLoading;
            }

            set
            {
                if (this.isLoading != value)
                {
                    this.isLoading = value;
                    RaisePropertyChanged("IsLoading");
                }
            }
        }

        public bool IsUpdating
        {
            get
            {
                return this.isUpdating;
            }

            set
            {
                if (this.isUpdating != value)
                {
                    this.isUpdating = value;
                    RaisePropertyChanged("IsUpdating");
                }

                this.IsUpdateFeedItemsEnabled = this.CanUpdateFeedItems();
            }
        }

        public bool IsEnabled
        {
            get
            {
                return this.isEnabled;
            }

            set
            {
                if (this.isEnabled != value)
                {
                    this.isEnabled = value;
                    RaisePropertyChanged("IsEnabled");
                }
            }

        }

        public bool IsUpdateFeedItemsEnabled
        {
            get
            {
                return this.isUpdateFeedItemsEnabled;
            }

            set
            {
                if (this.isUpdateFeedItemsEnabled != value)
                {
                    this.isUpdateFeedItemsEnabled = value;
                    RaisePropertyChanged("IsUpdateFeedItemsEnabled");
                }
            }
        }

        public ObservableCollection<FeedViewModel> Feeds
        {
            get
            {
                return this.feeds;
            }

            set
            {
                if (this.feeds != value)
                {
                    this.feeds = value;
                    RaisePropertyChanged("Feeds");
                }
            }
        }

        public ICommand UpdateFeedItemsCommand
        {
            get
            {
                if (this.updateFeedItemsCommand == null)
                {
                    this.updateFeedItemsCommand = new RelayCommand(this.OnUpdateFeedItems);
                }

                return this.updateFeedItemsCommand;
            }
        }
        #endregion

        #region Methods
        public override void Cleanup()
        {
            if (this.service != null)
            {
                this.service.GetFeedsCompleted -= new ServiceResponse<ReadOnlyCollection<IFeed>>(this.OnGetFeedsCompleted);
                this.service.UpdateFeedItemsCompleted -= new ServiceResponse<bool>(this.OnUpdateFeedItemsCompleted);

                this.service.Cleanup();
                this.service = null;
            }

            if (this.Feeds != null)
            {
                foreach (FeedViewModel item in this.Feeds)
                {
                    item.PropertyChanged -= new PropertyChangedEventHandler(this.OnFeedItemPropertyChanged);
                    item.Cleanup();
                }

                this.Feeds.Clear();
                this.Feeds = null;
            }

            base.Cleanup();
        }

        private void LoadFeeds()
        {
            this.IsLoading = true;
            this.service.GetFeedsAsync();
        }

        private void SetIsAllSelected()
        {
            bool allchecked = true;
            if (this.Feeds != null)
            {
                foreach (FeedViewModel item in this.Feeds)
                {
                    if (!item.IsSelected)
                    {
                        allchecked = false;
                    }
                }
            }

            this.isAllSelected = allchecked;
            RaisePropertyChanged("IsAllSelected");
        }

        private void SelectAllFeeds(bool select)
        {
            if (this.Feeds != null)
            {
                foreach (FeedViewModel item in this.Feeds)
                {
                    item.IsSelected = select;
                }
            }
        }

        private void UpdateFeedItems()
        {
            if (this.Feeds != null)
            {
                foreach (FeedViewModel item in this.Feeds)
                {
                    if (item.Status == FeedViewModel.FeedItemStatus.Pending)
                    {
                        item.Status = FeedViewModel.FeedItemStatus.Pending;
                        item.IsUpdating = true;
                        this.service.UpdateFeedItemsAsync(item.FeedId, item);
                        return;
                    }
                }
            }

            this.IsEnabled = true;
            this.IsUpdating = false;
        }
        #endregion

        #region Events
        private void OnGetFeedsCompleted(ServiceResponseArgs<ReadOnlyCollection<IFeed>> e)
        {
            this.IsLoading = false;

            if (e.Error != null)
            {
                // TODO
            }
            else
            {
                this.sourceFeeds = e.Result;
                this.Feeds = FeedViewModel.Convert(e.Result);

                foreach (FeedViewModel item in this.Feeds)
                {
                    item.PropertyChanged += new PropertyChangedEventHandler(this.OnFeedItemPropertyChanged);
                }
            }
        }

        private void OnFeedItemPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsSelected")
            {
                FeedViewModel feed = (FeedViewModel)sender;

                if (feed.IsSelected != this.IsAllSelected)
                {
                    this.SetIsAllSelected();
                }

                this.IsUpdateFeedItemsEnabled = this.CanUpdateFeedItems();
            }
        }

        private void OnUpdateFeedItemsCompleted(ServiceResponseArgs<bool> e)
        {
            FeedViewModel feed = (FeedViewModel)e.UserState;
            feed.IsUpdating = false;

            if (e.Error != null)
            {
                feed.Status = FeedViewModel.FeedItemStatus.Error;
            }
            else
            {
                feed.Status = FeedViewModel.FeedItemStatus.Done;
            }

            this.UpdateFeedItems();
        }

        private void OnUpdateFeedItems()
        {
            if (this.CanUpdateFeedItems())
            {
                this.IsUpdating = true;
                this.IsEnabled = false;

                if (this.Feeds != null)
                {
                    foreach (FeedViewModel item in this.Feeds)
                    {
                        if (item.IsSelected)
                        {
                            item.Status = FeedViewModel.FeedItemStatus.Pending;
                        }
                        else
                        {
                            item.Status = FeedViewModel.FeedItemStatus.None;
                        }
                    }
                }

                this.UpdateFeedItems();
            }
        }

        private bool CanUpdateFeedItems()
        {
            if (this.IsUpdating)
            {
                return false;
            }

            if (this.Feeds != null)
            {
                foreach (FeedViewModel item in this.Feeds)
                {
                    if (item.IsSelected)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        #endregion
    }
}
